package com.javacv.plus.extensions.image.steps;

import com.javacv.plus.core.processor.ProcessorContext;
import com.javacv.plus.core.processor.ProcessorStep;
import com.javacv.plus.extensions.image.ImageProcessor;
import com.javacv.plus.extensions.image.ProcessorResult;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.opencv.opencv_core.Mat;
import org.bytedeco.opencv.opencv_core.Size;

import static org.bytedeco.opencv.global.opencv_imgproc.*;

/**
 * 图像滤镜处理步骤
 * 支持基本的图像滤镜效果
 */
@Slf4j
public class FilterStep implements ProcessorStep<ImageProcessor, ProcessorResult> {
    
    public enum FilterType {
        GAUSSIAN_BLUR("高斯模糊"),
        MEDIAN_BLUR("中值模糊"),
        BILATERAL("双边滤波"),
        CANNY("Canny边缘");
        
        private final String description;
        
        FilterType(String description) {
            this.description = description;
        }
        
        public String getDescription() {
            return description;
        }
    }
    
    private final FilterType filterType;
    private final double intensity;
    
    /**
     * 创建滤镜步骤
     * @param filterType 滤镜类型
     * @param intensity 强度 (0.0-1.0)
     */
    public FilterStep(FilterType filterType, double intensity) {
        this.filterType = filterType;
        this.intensity = Math.max(0.0, Math.min(1.0, intensity));
    }
    
    @Override
    public ProcessorResult execute(ImageProcessor processor, ProcessorContext context) throws Exception {
        Mat currentImage = context.getAttribute("currentImage");
        if (currentImage == null || currentImage.empty()) {
            throw new IllegalStateException("当前图像为空，无法应用滤镜");
        }
        
        Mat filteredImage = new Mat();
        
        try {
            switch (filterType) {
                case GAUSSIAN_BLUR:
                    applyGaussianBlur(currentImage, filteredImage);
                    break;
                case MEDIAN_BLUR:
                    applyMedianBlur(currentImage, filteredImage);
                    break;
                case BILATERAL:
                    applyBilateralFilter(currentImage, filteredImage);
                    break;
                case CANNY:
                    applyCannyFilter(currentImage, filteredImage);
                    break;
                default:
                    throw new UnsupportedOperationException("不支持的滤镜类型: " + filterType);
            }
            
            context.setAttribute("currentImage", filteredImage);
            
            log.info("滤镜应用成功: {}，强度: {}", filterType.getDescription(), intensity);
            return null;
            
        } catch (Exception e) {
            if (filteredImage != null) {
                filteredImage.release();
            }
            throw new RuntimeException("滤镜应用失败: " + filterType.getDescription(), e);
        }
    }
    
    /**
     * 高斯模糊
     */
    private void applyGaussianBlur(Mat src, Mat dst) {
        int kernelSize = (int)(15 * intensity) | 1; // 确保是奇数
        kernelSize = Math.max(1, kernelSize);
        double sigma = kernelSize / 3.0;
        GaussianBlur(src, dst, new Size(kernelSize, kernelSize), sigma);
    }
    
    /**
     * 中值模糊
     */
    private void applyMedianBlur(Mat src, Mat dst) {
        int kernelSize = (int)(15 * intensity) | 1; // 确保是奇数
        kernelSize = Math.max(1, kernelSize);
        medianBlur(src, dst, kernelSize);
    }
    
    /**
     * 双边滤波
     */
    private void applyBilateralFilter(Mat src, Mat dst) {
        int d = (int)(20 * intensity);
        d = Math.max(1, d);
        double sigmaColor = 50 + 50 * intensity;
        double sigmaSpace = 50 + 50 * intensity;
        bilateralFilter(src, dst, d, sigmaColor, sigmaSpace);
    }
    
    /**
     * Canny边缘检测
     */
    private void applyCannyFilter(Mat src, Mat dst) {
        Mat gray = new Mat();
        if (src.channels() > 1) {
            cvtColor(src, gray, COLOR_BGR2GRAY);
        } else {
            gray = src.clone();
        }
        
        double threshold1 = 50 + 100 * intensity;
        double threshold2 = 150 + 100 * intensity;
        Canny(gray, dst, threshold1, threshold2);
        
        // 转换回彩色图像
        if (src.channels() > 1) {
            Mat colorCanny = new Mat();
            cvtColor(dst, colorCanny, COLOR_GRAY2BGR);
            dst.release();
            dst = colorCanny;
        }
        
        gray.release();
    }
    
    @Override
    public String getStepName() {
        return "Filter-" + filterType.name();
    }
    
    @Override
    public int getPriority() {
        return 60; // 在基本处理之后，保存之前
    }
} 